package com.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.dao.ArticleDAO;
import com.model.Article;
import com.model.Tag;
import com.util.Page;

@Repository
public class ArticleDAOImpl implements ArticleDAO {
	@Autowired
	private SessionFactory sessionFactory;

	public Article add(Article article) {
		try {
			sessionFactory.getCurrentSession().save(article);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return article;
	}

	public Article update(Article article) {
		sessionFactory.getCurrentSession().update(article);
		return article;
	}

	public int delete(int id) {
		Session s = sessionFactory.getCurrentSession();
		String sql = "delete from article where id=:id";
		Query query = s.createSQLQuery(sql);
		query.setInteger("id", id);
		query.executeUpdate();
		return id;
	}

	public Article findById(int id) {
		Article article = (Article) sessionFactory.getCurrentSession().get(Article.class, id);
		return article;
	}

	public Article findByIdWithUser(int articleId) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "From Article a inner join fetch a.user u where a.id=:id";
		Query query = s.createQuery(hql);
		query.setInteger("id", articleId);
		List<Article> list = query.list();
		if (list.size() > 0) {
			return list.get(0);
		}
		else {
			return null;
		}
	}

	public void addTag(int articleId, int tagId) {
		Session s = sessionFactory.getCurrentSession();
		String sql = "insert into article_tag(article_id,tag_id) values(:articleId,:tagId)";
		Query query = s.createSQLQuery(sql);
		query.setInteger("articleId", articleId);
		query.setInteger("tagId", tagId);
		query.executeUpdate();
	}

	public void deleteTag(int articleId, int tagId) {
		try {
			Session s = sessionFactory.getCurrentSession();
			String sql = "delete from article_tag where article_id=:articleId and tag_id=:tagId";
			Query query = s.createSQLQuery(sql);
			query.setInteger("articleId", articleId);
			query.setInteger("tagId", tagId);
			query.executeUpdate();
		}
		catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	public boolean isTagExist(int articleId, int tagId) {
		Session s = sessionFactory.getCurrentSession();
		String sql = "select count(*) from article_tag where article_id=:articleId and tag_id=:tagId";
		Query query = s.createSQLQuery(sql);
		query.setInteger("articleId", articleId);
		query.setInteger("tagId", tagId);

		int count = Integer.parseInt((query.uniqueResult().toString()));

		if (count > 0) {
			return true;
		}
		else {
			return false;
		}
	}

	public Page findPageByUserId(int userId, int page, int pageSize, boolean isPublic) {

		Session s = sessionFactory.getCurrentSession();
		String hql = "select a.*,u.id as user_id,u.name as user_name,u.head_img as user_head from article a inner join user u on a.user_id=u.id where a.user_id=:userId";
		String hqlc = "select count(*) from article a where a.user_id=:userId";

		if (isPublic) {
			hql += " and a.is_public=1";
			hqlc += " and a.is_public=1";
		}
		hql += " order by a.create_at desc";

		Query query = s.createSQLQuery(hql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		Query queryc = s.createSQLQuery(hqlc);

		query.setInteger("userId", userId);
		queryc.setInteger("userId", userId);

		query.setMaxResults(pageSize);
		query.setFirstResult((page - 1) * pageSize);

		int count = Integer.parseInt((queryc.uniqueResult().toString()));
		Page pageIns = new Page(count, pageSize, page);
		pageIns.setList(query.list());
		return pageIns;

	}

	@SuppressWarnings("unchecked")
	public List<Article> findCollectPageByUserId(int userId, int page, int pageSize) {

		Session s = sessionFactory.getCurrentSession();
		String hql = "select a From Article a inner join fetch a.user u where a.id in (select aa.article.id from ArticleAction aa where aa.user.id=:userId and aa.actionType='collect') order by a.createAt desc";

		Query query = s.createQuery(hql);
		query.setInteger("userId", userId);
		query.setMaxResults(pageSize);
		query.setFirstResult((page - 1) * pageSize);

		return query.list();

	}

	public void makePublic(int articleId, boolean isPublic) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "update Article as a set a.isPublic=:isPublic where a.id=:id";
		Query q = s.createQuery(hql);
		q.setInteger("id", articleId);
		if (isPublic) {
			q.setInteger("isPublic", 1);
		}
		else {
			q.setInteger("isPublic", 0);
		}
		q.executeUpdate();
	}

	public void addFavorNum(int articleId) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "update Article as a set a.favorNum=a.favorNum+1 where a.id=:id";
		Query q = s.createQuery(hql);
		q.setInteger("id", articleId);
		q.executeUpdate();

	}

	public void addAgreeNum(int articleId) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "update Article as a set a.agreeNum=a.agreeNum+1 where a.id=:id";
		Query q = s.createQuery(hql);
		q.setInteger("id", articleId);
		q.executeUpdate();
	}

	public void addDisagreeNum(int articleId) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "update Article as a set a.disagreeNum=a.disagreeNum+1 where a.id=:id";
		Query q = s.createQuery(hql);
		q.setInteger("id", articleId);
		q.executeUpdate();
	}

	public void addCollectNum(int articleId) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "update Article as a set a.collectNum=a.collectNum+1 where a.id=:id";
		Query q = s.createQuery(hql);
		q.setInteger("id", articleId);
		q.executeUpdate();

	}

	@SuppressWarnings("rawtypes")
	public List<HashMap> findByIds(String articleIds) {
		if (articleIds.length() == 0)
			return new ArrayList<HashMap>();
		Session s = sessionFactory.getCurrentSession();
		String hql = "select a From Article a inner join fetch a.user u where a.id in ("
				+ articleIds + ")";
		String sql = "select a.*,u.id as user_id,u.name as user_name,u.head_img as user_head from article a inner join user u on a.user_id=u.id where a.id in ("
				+ articleIds + ")";
		Query q = s.createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

		List list = q.list();
		return list;
	}

	public void reduceCollectNum(int articleId) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "update Article as a set a.collectNum=a.collectNum-1 where a.id=:id";
		Query q = s.createQuery(hql);
		q.setInteger("id", articleId);
		q.executeUpdate();
	}

	public List<Tag> findTagsByArticleId(int articleId) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "select t.* from tag t where t.id in (select at.tag_id from article_tag as at where at.article_id=:articleId)";
		Query query = s.createSQLQuery(hql).addEntity(Tag.class);
		query.setInteger("articleId", articleId);
		List<Tag> tags = query.list();
		return tags;
	}

	public void addCommentNum(int aid) {
		Session s = sessionFactory.getCurrentSession();
		String hql = "update Article as a set a.commentsNum=a.commentsNum+1 where a.id=:id";
		Query q = s.createQuery(hql);
		q.setInteger("id", aid);
		q.executeUpdate();
	}

	public List findNewArticleTopN(int topN) {
		// TODO Auto-generated method stub
		Session s = sessionFactory.getCurrentSession();
		String hql = "select a From Article a inner join fetch a.user u where a.isPublic=1 order by a.createAt desc";

		Query query = s.createQuery(hql);
		query.setMaxResults(topN);

		return query.list();
	}

	public List findHotArticleTopN(int topN) {
		// TODO Auto-generated method stub
		Session s = sessionFactory.getCurrentSession();
		String hql = "select a From Article a inner join fetch a.user u where a.isPublic=1 order by (a.commentsNum+a.collectNum+a.disagreeNum+a.agreeNum+a.favorNum) desc";

		Query query = s.createQuery(hql);
		query.setMaxResults(topN);

		return query.list();
	}

}
